import DingInfo from "../config";
import { postRequest } from "request";
import { util, InsideErr, BaseErr } from "utils";
import { toRequestSecretData } from "./requestSecretData";
import { formatterContent } from "./formatterContent";
const db = uniCloud.database();
const collection = db.collection("token-valid");
// 默认的
const DefaultDingDingDocToken = "NjAzMjA1NzIwZGcFbLjwAZPVCQfFvnWicjQhefhmWdmU";
const DingDingTokenType = "dingding-doc";
// 获取db 缓存
async function getDbCache(): Promise<[err?: BaseErr, data?: any]> {
    let [err, res] = await util.awaitWrap(
        collection
            .where({
                "token-type": DingDingTokenType,
            })
            .limit(1)
            .get()
    );
    if (err) {
        return [new InsideErr(err), undefined];
    }
    let { data = [] } = res || {};
    return [undefined, data[0]];
}
// 修改dingdingToken 有效
async function changeDingToken(valid: boolean, docId?: string) {
    if (docId) {
        await collection.doc(docId).update({
            valid,
            update: util.baseDateDes(new Date()),
        });
    }
}

// 获取钉钉token
async function getDingDingToken(): Promise<
    [err?: BaseErr, data?: { id?: string; token?: string; valid: boolean }]
> {
    let [err, data] = await getDbCache();
    if (!util.nilValue(err)) {
        return [err, undefined];
    }
    let dingToken: { id?: string; token?: string; valid: boolean } = {
        valid: false,
    };
    if (util.nilValue(data)) {
        // 写入 数据库
        let res = await collection.add({
            token: DefaultDingDingDocToken,
            "token-type": DingDingTokenType,
            valid: true,
            update: util.baseDateDes(new Date()),
        });

        dingToken = {
            token: DefaultDingDingDocToken,
            valid: true,
            id: res.id,
        };
    } else {
        dingToken = {
            token: data.token,
            valid: data.valid,
            id: data._id,
        };
    }
    if (util.nilValue(dingToken.token)) {
        return [new BaseErr(-4001, "dingding-token获取失败"), undefined];
    }
    return [undefined, dingToken];
}

// 请求 数据
async function requestDocData(token: string) {
    const DingDocApi = DingInfo.dingApi;
    const postData = {
        pageMode: 2,
        orgGrayKeys: ["enable_notable_frontend"],
        enableSlice: true,
        anchor: {
            needSheetSkeleton: true,
        },
    };
    const headers = {
        ...DingInfo.dingHeader,
        cookie: `doc_atoken=${token}`,
        pragma: "no-cache",
    };
    return await postRequest(DingDocApi)(postData, {
        // enableProxy: true,
        // rejectUnauthorized: false,
        // proxy: "http://127.0.0.1:8899",
        contentType: "json",
        headers,
    });
}

// 获取文本数据
async function getDocInfo(docData: AnyObject, tokenId?: string): Promise<[BaseErr?, any?]> {
    let { status, data } = docData || {};
    if (status !== 200) {
        // 把token 弄成 失效
        await changeDingToken(false, tokenId);
        return [new BaseErr(-4007, `token 可能失效了,  doc数据状态码 ${status}`), undefined];
    }
    let checkpoint = data?.documentContent?.checkpoint ?? {};
    let { secretInfo, ecpOssUrl, content } = checkpoint;
    if (!util.nilValue(secretInfo) && !util.nilValue(ecpOssUrl)) {
        // 这个要 额外 处理
        return await toRequestSecretData(secretInfo, ecpOssUrl);
    }
    if (!util.nilValue(content)) {
        return formatterContent(content);
    }
    return [new BaseErr(-4003, "返回的数据不对"), undefined];
}

// 获取解析后的数据
async function getDocData(): Promise<[err?: BaseErr, data?: any]> {
    // 获取数据库中的 doc_token
    let [err, token] = await getDingDingToken();
    if (!util.nilValue(err)) {
        return [err, undefined];
    }
    if (token?.valid !== true || util.nilValue(token?.token)) {
        // 失效了
        return [new BaseErr(-4009, "token  已失效"), undefined];
    }

    let [doc_err, doc_data] = await requestDocData(token.token!);
    if (!util.nilValue(doc_err)) {
        // 把 token 设置为无效
        return [doc_err, undefined];
    }
    return await getDocInfo(doc_data, token.id);
}

export { getDocData };
